#pragma
#include<iostream>
#include<queue>
#include<string>
using namespace std;
#include<pthread.h>
const static int defaultcap = 5;
template <typename T>
class BlockQueue
{
public:
    BlockQueue(int cap = defaultcap):_max_cap(cap)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_pcond, nullptr);
        pthread_cond_init(&_ccond, nullptr);
    }
    void Equeue(const T& in)
    {
        pthread_mutex_lock(&_mutex);
        while(ifFull())
        {
            //被调用时，除了让自己继续排队，还会自己释放传入的锁，返回时必须参与锁的竞争，重新加上锁
            pthread_cond_wait(&_pcond, &_mutex);
        }
        //需要补充了
        _block_queue.push(in);
        pthread_mutex_unlock(&_mutex);
        //通知消费者可以消费
        pthread_cond_signal(&_ccond);
    }
    void Pop(T* out)
    {
        pthread_mutex_lock(&_mutex);
        while(ifEmpty())
        {
            pthread_cond_wait(&_ccond, &_mutex);
        }
        //有货，可以买
        *out = _block_queue.front();
        _block_queue.pop();
        pthread_mutex_unlock(&_mutex);
        pthread_cond_signal(&_pcond);
    }

private:
    bool ifFull()
    {
       return _block_queue.size() == _max_cap;
    }
    bool ifEmpty()
    {
        return _block_queue.empty();
    }
    queue<T> _block_queue;
    int _max_cap;
    pthread_mutex_t _mutex;
    pthread_cond_t _pcond;
    pthread_cond_t _ccond;
};